#include "HttpServer.hpp"
#include "Util.hpp"
#include <iostream>
#include <vector>
#include <memory>

const std::string sep = "\r\n";
const std::string webRoot = "./wwwroot";
const std::string defaultHomePage = "index.html";
using namespace httpserver_ns;

// 一般一个webserver，不做特殊说明，如果用户之间默认访问‘/’, 我们绝对不能把把整站给对方
// 需要添加默认首页！！而且，不能让用户访问wwwroot里面的任何一个目录本身，也可以给每一个目录都带上一个默认首页
// -张网页，可能会包含很多的要素资源，每一个资源都要发起一次http request
class HttpRequest
{
public:
    HttpRequest(const std::string& root = webRoot): _path(root)
    {}

    ~HttpRequest()
    {}
public:
    std::string _method; // 获取方法
    std::string _url; // 获取需要访问资源的地址
    std::string _version; // http版本

    std::vector<std::string> _body;

    std::string _path;
    std::string _suffix; // 从URL中找后缀
};

std::string GetContentType(const std::string& suffix)
{
    std::string ret = "Content-Type: ";
    if(suffix == ".html")
        ret += "text/html";
    else if(suffix == ".jpg")
        ret += "image/jpeg";
    
    return ret;
}

// 反序列化
HttpRequest Deserialize(std::string& request)
{
    HttpRequest rq;
    // 首列报头处理
    std::string headLine = Util::ReadHead(request, sep);
    Util::PaueseLine(headLine, &rq._method, &rq._url, &rq._version);

    while(!request.empty())
    {
        headLine = Util::ReadHead(request, sep);
        rq._body.push_back(headLine);
    }

    rq._path += rq._url;
    if (rq._path[rq._path.size() - 1] == '/')
        rq._path += defaultHomePage;

    auto pos = rq._url.rfind(".");
    if(pos == std::string::npos)
        rq._suffix = ".html";
    else
        rq._suffix = rq._url.substr(pos);

    return rq;
}

std::string HandlerHttp(std::string& request)
{
    // 请求
    // 空行
    // 正文 hello http
    // body Content-Length Content-Type
    // body 文件化 webRoot
    std::cout << "--------------------" << std::endl;
    std::cout << request << std::endl;

    HttpRequest rq = Deserialize(request);

    std::string response;
    std::string body;
    Util::ReadFile(rq._path, body);

    response += "HTTP/1.0 200 OK" + sep;
    response += "Content-Length: " + body.size() + sep;
    response += GetContentType(rq._suffix) + sep; 
    response += sep;
    response += body;

    return response;
}

int main(int argc, char* argv[])
{
    uint16_t port = atoi(argv[1]);
    std::unique_ptr<HttpServer> server(new HttpServer(HandlerHttp, port));

    server->InitServer();
    server->Start();
    return 0;
}